import java.util.Map;
import java.util.HashMap;

public class EvalVistor extends LabeledExprBaseVisitor<Integer> {
    
    // 计算器的 “内存”， 存放变量名和变量值的对应关系
    Map<String, Integer> memory = new HashMap<>();

    // ID '=' expr NEWLINE # assign
    @Override 
    public Integer visitAssign(LabeledExprParser.AssignContext ctx) { 
        // id在'='的左侧
        String id = ctx.ID().getText();
        // 计算右侧表达式的值
        int value = visit(ctx.expr());
        // 将这个映射关系存储在计算器的"内存"中
        memory.put(id, value);
        return value;
    }

    // expr NEWLINE  #printExpr
    @Override 
    public Integer visitPrintExpr(LabeledExprParser.PrintExprContext ctx) { 
        // 计算expr子节点的值
        Integer value = visit(ctx.expr());
        // 打印结果
        System.out.println(value);
        // 上面已经直接打印除了结果，因此这里返回一个假值即可
        return 0;
    }

    // INT
    @Override 
    public Integer visitInt(LabeledExprParser.IntContext ctx) { 
        return Integer.valueOf(ctx.INT().getText()); 
    }

    // ID
    @Override 
    public Integer visitId(LabeledExprParser.IdContext ctx) { 
        String id = ctx.ID().getText();
        if (memory.containsKey(id)) 
            return memory.get(id);

        return 0; 
    }

    // expr op=('*'|'/') expr # MulDiv
    @Override 
    public Integer visitMulDiv(LabeledExprParser.MulDivContext ctx) { 
        // 计算左侧子表达式的值
        int left = visit(ctx.expr(0));
        // 计算右侧子表达式的值
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabeledExprParser.MUL) 
            return left * right;
        else 
            return left / right;
    }

    // expr op=('+'|'-') expr # AddSub
    @Override 
    public Integer visitAddSub(LabeledExprParser.AddSubContext ctx) { 
        // 计算左侧子表达式的值
        int left = visit(ctx.expr(0));
        // 计算右侧子表达式的值
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabeledExprParser.ADD) 
            return left + right;
        else 
            return left - right;
    }

    // '(' expr ')' # parens
    @Override 
    public Integer visitParens(LabeledExprParser.ParensContext ctx) { 
        return visit(ctx.expr()); // 返回字表达式的值
    }

    @Override 
    public Integer visitClear(LabeledExprParser.ClearContext ctx) { 
        // System.out.println(ctx.CLEAR().getText());
        System.out.println("Before clear memory size " + memory.size());
        memory.clear();
        System.out.println("After clear memory size " + memory.size());
        return 0;
    }
}
